<?php
require_once($_SERVER["DOCUMENT_ROOT"] . "/include/config.php");
require_once("sql.php");

class ConnectionController extends BaseController
{
    static public function ProcessRequest($request)
    {
        self::SQL_connect();

        if ($request == "save_route") {
            if (isset($_POST["route"])) {
                $route = json_decode($_POST["route"]);
                self::SaveRoute($route);
            }
        } else if ($request == "get_routes") {
            self::GetRoutes($_POST["layer"]);
        } else if ($request == "get_point") {
            if (isset($_POST["id"]))
                self::GetPoint($_POST["id"]);
        } else if ($request == "save_point") {
            if (isset($_POST["data"]))
                self::SavePoint(json_decode($_POST["data"]));
        } else if ($request == "save_segment") {
            if (isset($_POST["data"]))
                self::SaveSegment(json_decode($_POST["data"]));
        } else if ($request == "get_connections" && isset($_POST["data"]))
            self::GetConnections(json_decode($_POST["data"]));
        else if ($request == "get_struct" && isset($_POST["data"]))
            self::GetSegmentsStructure(json_decode($_POST["data"]));
        else if ($request == "delete_point" && isset($_POST["id"]))
            self::DeletePoint($_POST["id"]);
        else if ($request == "delete_segment" && isset($_POST["id"]))
            self::DeleteSegment($_POST["id"]);
        else if ($request == "save_connections" && isset($_POST["data"]))
            self::SaveConnections(json_decode($_POST["data"]));
        else if ($request == "update_network" && isset($_POST["data"]))
            self::UpdateNetwork(json_decode($_POST["data"]));
        else if ($request == "save_connectpoint" && isset($_POST["data"]))
            self::SaveConnectPoint(json_decode($_POST["data"]));
        else if ($request == "delete_connection" && isset($_POST["id"]))
            self::DeleteConnection($_POST["id"]);
        else if ($request == "merge_segments" && isset($_POST["data"]))
            self::MergeSegments(json_decode($_POST["data"]));
        else if ($request == "delete_connect_point" && isset($_POST["id"]))
            self::DeleteConnectionPoint($_POST["id"]);
        else if ($request == "can_create_connection_between_segments")
            self::CanCreateConnectionBetweenSegments($_POST["unit1"], $_POST["unit2"], $_POST["pointID"]);
        else if ($request == "delete_connection_between_segments")
            self::DeleteConnectionBetweenSegments($_POST["segment1"], $_POST["segment2"]);
        else if ($request == "can_merge_segments")
            self::CanMergeSegments($_POST["segment1"], $_POST["segment2"], $_POST["pointID"]);
        else if ($request == "get_connections_at_point")
            self::GetConnectionsAtConnectionPoint($_POST["connection_point_id"]);

        self::SQL_close();
    }

    static private function GetConnectionsAtConnectionPoint($connectionPointID)
    {
        $query = "call GetConnections('$connectionPointID');";
        $response = array();

        if (self::$db_link->multi_query($query)) {
            if ($result = self::$db_link->use_result()) {
                $i = 0;
                while ($row = $result->fetch_object()) {
                    $response[$i++] = $row;
                }
                do {
                    if ($result = self::$db_link->store_result())
                        $result->free();
                } while (self::$db_link->next_result());
            }
            echo json_encode((object)array("success" => true, "connections" => $response));
        } else {
            json_encode((object)array("success" => false, "error" => self::$db_link->error));
        }
    }

    static private function GenerateGUID()
    {
        $tmp = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            // 32 bits for "time_low"
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),

            // 16 bits for "time_mid"
            mt_rand(0, 0xffff),

            // 16 bits for "time_hi_and_version",
            // four most significant bits holds version number 4
            mt_rand(0, 0x0fff) | 0x4000,

            // 16 bits, 8 bits for "clk_seq_hi_res",
            // 8 bits for "clk_seq_low",
            // two most significant bits holds zero and one for variant DCE1.1
            mt_rand(0, 0x3fff) | 0x8000,

            // 48 bits for "node"
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );

        return str_replace("-", "", $tmp);
    }

    static private function CanMergeSegments($segment1, $segment2, $pointID)
    {
        $query = "Call CanMergeSegments('$segment1', '$segment2', '$pointID');";
        $result = self::$db_link->query($query)->fetch_assoc();
        echo json_encode((object)array("success" => $result['num'] == 0));
    }

    static private function  CanCreateConnectionBetweenSegments($unit1, $unit2, $pointID)
    {
        $query = "select count(*) as num from connections where id_point = '$pointID' and ((left_unit_type = 'segment' && left_unit in ('$unit1', '$unit2')) or
            (right_unit_type = 'segment' and right_unit in ('$unit1', '$unit2')));";
        $result = self::$db_link->query($query)->fetch_assoc();
        echo json_encode((object)array("success" => $result['num'] == 0));
    }

    static private function UpdateNetwork($data)
    {
        $query = "";
        foreach ($data as $id => $coords) {
            $query .= "UPDATE support_points SET location = '$coords' WHERE id = '$id';";
        }
        self::ProcessQuery($query);
    }

    static private function GetRoutes($layer)
    {
        $query = "select *, (SELECT COUNT(*) > 0 from connect_points where connect_points.id_support_point = support_points.id) as connection
		from support_points";
        if (intval($layer) < 3) $query .= " WHERE layer= $layer or layer = 3";
        $query .= ";SELECT segments.id, start_point, end_point, cables.title FROM segments LEFT JOIN cables on segments.id_cable = cables.id;";
        if (self::$db_link->multi_query($query)) {
            $points = Array();
            $segments = Array();

            if ($result = self::$db_link->store_result()) {
                while ($row = $result->fetch_object())
                    $points[$row->id] = (object)array("title" => $row->title, "location" => json_decode($row->location), "connection" => $row->connection);
                $result->free();
                self::$db_link->next_result();
            }

            if ($result = self::$db_link->store_result()) {
                while ($row = $result->fetch_object()) {
                    if (isset($points[$row->start_point]) && isset($points[$row->end_point]))
                        $segments[$row->id] = (object)array("start" => $points[$row->start_point]->location, "end" => $points[$row->end_point]->location, "title" => $row->title);
                }
                $result->free();
            }
            echo json_encode((object)array("points" => $points, "segments" => $segments));
        }
    }

    static private function SaveRoute($route)
    {
        $query = "";
        foreach ($route->points as $point) {
            $loc = json_encode($point->location);
            if (!$point->old)
                $query .= "INSERT INTO support_points (id, location, layer) VALUES('$point->id', '$loc',$route->layer);";
        }
        for ($i = 0; $i < count($route->points) - 1; $i++) {
            $start_id = $route->points[$i]->id;
            $end_id = $route->points[$i + 1]->id;
            $id = $route->id[$i];
            $query .= "INSERT INTO segments (id, start_point, end_point, id_cable) VALUES('$id', '$start_id', '$end_id', '$route->cable');";
        }

        for ($i = 1; $i < count($route->points) - 1; $i++) {
            $point = $route->points[$i]->id;
            $id1 = $route->id[$i - 1];
            $id2 = $route->id[$i];
            $id = md5(uniqid());
            $query .= "INSERT INTO connections (id, id_point, left_unit, right_unit, left_unit_type, right_unit_type) VALUES ('$id', '$point', '$id1', '$id2', 'segment', 'segment');";
        }

        self::ProcessQuery($query);
    }

    static public function GetPoint($id)
    {

        $query = "SELECT support_points.id, support_points.title, location, comment, id_type, layer FROM support_points
		LEFT JOIN support_points_type on support_points_type.id = id_type WHERE support_points.id = '$id';
		SELECT * from connect_points where id_support_point = '$id' ORDER BY name;";

        if (self::$db_link->multi_query($query)) {
            if ($result = self::$db_link->store_result()) {
                $row = $result->fetch_object();
                $data = (array)$row;
                $data["connect_points"] = array();
                $data = (object)$data;
                $result->free();
            }

            self::$db_link->next_result();
            if ($result = self::$db_link->store_result()) {
                while ($row = $result->fetch_object()) {
                    $data->connect_points[] = $row;
                }
            }
            echo json_encode($data);
        }
    }

    static private function SavePoint($point)
    {
        $type = "null";
        if ($point->type)
            $type = "'$point->type'";
        $query = "INSERT INTO support_points (id, location, title, comment, id_type, layer) VALUES ('$point->id','$point->location','$point->title','$point->comment',$type, $point->layer)
			ON DUPLICATE KEY UPDATE location = '$point->location', title ='$point->title', comment = '$point->comment', id_type = $type, layer = $point->layer;";
        if (isset($point->change))
            $query .= "DELETE FROM connections WHERE id_point='$point->id';";
        self::ProcessQuery($query);
    }

    static public function GetSegment($id)
    {
        self::SQL_connect();
        $query = "CALL GetSegment('$id');";
        if ($result = self::$db_link->query($query))
            $row = $result->fetch_object();
        else return self::$db_link->error;
        self::SQL_close();
        return $row;
    }

    static private function SaveSegment($segment)
    {
        $query = "INSERT INTO segments (id, id_cable, length, attenuation) VALUES ('$segment->id', '$segment->cable', $segment->length, $segment->attenuation)
		ON DUPLICATE KEY UPDATE id_cable  = '$segment->cable', length=$segment->length, attenuation=$segment->attenuation;";
        self::ProcessQuery($query);
    }

    static private function DeletePoint($id)
    {
        $query = "DELETE FROM support_points WHERE id = '$id';";
        self::ProcessQuery($query);
    }

    static private function DeleteSegment($id)
    {
        $query = "DELETE FROM segments WHERE id = '$id'; DELETE FROM connections WHERE 
			(left_unit_type = 'segment' AND left_unit = '$id') OR (right_unit_type = 'segment' AND right_unit = '$id');";
        self::ProcessQuery($query);
    }

    static public function GetConnections($input)
    {
        $query = "SELECT location, (SELECT COUNT(*) > 0 from connect_points where connect_points.id_support_point = support_points.id) as connection from support_points where id='$input->id';";
        if (isset($input->cid))
            $query .= "SELECT * from connect_points where id = '$input->cid';";
        $query .= "CALL GetConnectionSchema('$input->id');";
        $query .= "CALL GetPointSegments('$input->id');";

        $data = (object)array("location" => 0, "connection" => 0, "segments" => Array(), "connections" => Array(), "connect_point" => null);
        if (self::$db_link->multi_query($query)) {
            if ($result = self::$db_link->store_result()) {
                $row = $result->fetch_object();
                $data->location = $row->location;
                $data->connection = $row->connection;
                $result->free();
                self::$db_link->next_result();
            }
            if (isset($input->cid)) {
                if ($result = self::$db_link->store_result()) {
                    if ($row = $result->fetch_object())
                        $data->connect_point = $row;
                    $result->free();
                    self::$db_link->next_result();
                }
            }
            if ($result = self::$db_link->store_result()) {
                while ($row = $result->fetch_object())
                    $data->connections[] = $row;
                $result->free();
                self::$db_link->next_result();
            }

            do {
                if ($result = self::$db_link->store_result()) {
                    while ($row = $result->fetch_object())
                        $data->segments[] = $row;
                }
            } while (self::$db_link->next_result());
        }
        echo json_encode($data);
    }

    static private function GetSegmentsStructure($data)
    {
        $response = (object)array("segments" => array());
        $query = "CALL GetSegmentStructure('$data->segment1'); CALL GetSegmentStructure('$data->segment2');";
        if (self::$db_link->multi_query($query)) {
            $i = -1;
            do {
                if ($result = self::$db_link->use_result()) {
                    $i++;
                    $response->segments[$i] = (object)array("modules" => array(), "id" => "");
                    while ($row = $result->fetch_object()) {

                        if (!isset($response->segments[$i]->modules[$row->mod_id])) {
                            $response->segments[$i]->modules[$row->mod_id] = (object)array("color" => $row->mod_color, "fibers" => array(), "number" => $row->mod_number, "id" => $row->mod_id);
                        }
                        $response->segments[$i]->id = $row->seg_id;
                        $response->segments[$i]->modules[$row->mod_id]->fibers[] = (object)array("id" => $row->id, "number" => $row->number, "color" => $row->color);
                    }
                    $result->close();
                }
            } while (self::$db_link->next_result());

            echo json_encode($response);
        } else {
            echo self::$db_link->error;
        }
    }

    static private function SaveConnectPoint($data)
    {
        $query = "INSERT INTO connect_points (id, name, type, id_support_point) VALUES ('$data->id', '$data->name', '$data->type', '$data->id_support')
		ON DUPLICATE KEY UPDATE name  = '$data->name', type='$data->type';";
        self::ProcessQuery($query);
    }

    static private function SaveConnections($data)
    {
        $query = "Call DeleteConnections('$data->cid');";

        foreach ($data->splitters as $item) {
            $query .= "insert into splitters (id, id_type, serial, id_connect_point) values ('$item->splitterID', '$item->typeID', NULL, '$data->cid');";
        }

        foreach ($data->connections as $item) {
            $leftUnitID = self::GenerateGUID();
            $leftUnitType = "";
            if ($item->left->type == 'fiber') {
                $query .= "insert into connections_unit_fiber (id, id_segment, id_fiber) values ('$leftUnitID', '" . $item->left->segmentID . "', '" . $item->left->fiberID . "');";
                $leftUnitType = "fiber";
            } else if ($item->left->type == "splitter") {
                $query .= "insert into connections_unit_splitter (id, id_splitter, input, number) values('$leftUnitID', '" . $item->left->splitterID . "', '" . $item->left->isInput . "', '" . $item->left->number . "');";
                $leftUnitType = "splitter";
            }

            $rightUnitID = self::GenerateGUID();
            $rightUnitType = "";
            if ($item->right->type == "fiber") {
                $query .= "insert into connections_unit_fiber (id, id_segment, id_fiber) values ('$rightUnitID', '" . $item->right->segmentID . "', '" . $item->right->fiberID . "');";
                $rightUnitType = "fiber";
            } else if ($item->right->type == "splitter") {
                $query .= "insert into connections_unit_splitter (id, id_splitter, input, number) values('$rightUnitID', '" . $item->right->splitterID . "', '" . $item->right->isInput . "', '" . $item->right->number . "');";
                $rightUnitType = "splitter";
            }

            $connectionID = self::GenerateGUID();
            $query .= "insert into connections (id, id_point, left_unit, right_unit, id_connect_point, left_unit_type, right_unit_type) values('$connectionID', '$data->point', '$leftUnitID', '$rightUnitID', '$data->cid', '$leftUnitType', '$rightUnitType');";
        }

        if (self::$db_link->multi_query($query))
            echo json_encode((object)array("success" => true));
        else
            echo(json_encode((object)array("success" => false, "error" => self::$db_link->error)));
    }

    static private function DeleteConnectionBetweenSegments($segment1, $segment2)
    {
        $query = "delete from connections where left_unit_type='segment' and right_unit_type='segment' and ((left_unit ='$segment1' and right_unit = '$segment2') or (left_unit ='$segment2' and right_unit = '$segment1'));";
        self::ProcessQuery($query);
    }

    static private function DeleteConnection($id)
    {
        $query = "DELETE FROM connections WHERE id = '$id'";
        self::ProcessQuery($query);
    }

    static private function MergeSegments($data)
    {
        $query = "INSERT INTO connections SET id = '$data->id', left_unit = '$data->segment1', right_unit = '$data->segment2', id_point='$data->point', left_unit_type='segment', right_unit_type='segment';";
        self::ProcessQuery($query);
    }

    static private function DeleteConnectionPoint($id)
    {
        $query = "Call DeleteConnections('$id'); delete from connect_points where id = '$id';";
        self::ProcessQuery($query);
    }

    static public function GetSplitterInfo($id)
    {
        self::SQL_connect();
        $query = "SELECT attenuation, title FROM splitters
                  LEFT JOIN splitters_types ON splitters_types.id = splitters.id_type
                  WHERE splitters.id = '$id';
                  SELECT output_number, splitters_attenuation.attenuation FROM splitters_attenuation
                  LEFT JOIN splitters_types on splitters_types.id = splitters_attenuation.id
                  LEFT JOIN splitters ON splitters_types.id = splitters.id_type
                  WHERE splitters.id = '$id'";

        $info = array("title" => "", "common_attenuation" => "", "attenuation" => array());
        if (self::$db_link->multi_query($query)) {
            if ($result = self::$db_link->store_result()) {
                 while ($row = $result->fetch_object()) {
                     $info["title"] = $row->title;
                     $info["common_attenuation"] = $row->attenuation;
                 }
                 self::$db_link->next_result();
            }

            if ($result = self::$db_link->store_result()) {
                while ($row = $result->fetch_object())
                    $info["attenuation"][$row->output_number] = floatval($row->attenuation);
                self::$db_link->next_result();
            }
        }
        self::SQL_close();
        return $info;

    }

    static public function GetAllConnectionsWithUnits()
    {
        self::SQL_connect();
        $data = array("points" => array(), "connections" => array(), "fiber" => array(), "splitters" => array(),
                "segments" => array());
        $query = "SELECT * FROM support_points;
                  SELECT * FROM connections;
                  SELECT * FROM connections_unit_fiber;
                  SELECT * FROM connections_unit_splitter;
                  SELECT segments.id, segments.start_point, segments.end_point, segments.length,
                   segments.attenuation as fact_attenuation, cables.attenuation, cables.title FROM segments
                   LEFT JOIN cables on cables.id = segments.id_cable;";
        if (self::$db_link->multi_query($query)) {
            foreach ($data as &$arr) {
                if ($result = self::$db_link->store_result()) {
                    while ($row = $result->fetch_object())
                        $arr[$row->id] = $row;

                    self::$db_link->next_result();
                }
            }
        }
        return (object)$data;
    }
}

ConnectionController::$config = $config;
if (isset($_POST["op"]))
    ConnectionController::ProcessRequest($_POST["op"]);
?>